
#ifndef _WEBSPIDERAROUND_H_
#define _WEBSPIDERAROUND_H_

#include <QString>
#include <QList>
#include <QTimer>
#ifndef Q_MOC_RUN 
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <boost/function.hpp>
#endif

#include "../core/operator.h"

#include <QDebug>

class WebSpiderCustom;
class Operator;

class WebSpiderRequest : public QObject {
    Q_OBJECT
    public:
    WebSpiderRequest(QString url, QString spiderName);
    ~WebSpiderRequest();

    QString url() {return m_url;}
    QString spiderName() {return m_name;}
    QString id() {return m_id;}
    long selfDestroyTime() {return m_selfDestroyTimeMS;}
    long timeoutTime() {return m_timeoutMs;}

    void setLevel(int level);
    int level();
    void parse(Operator *opt);
    void remove(Operator *opt);
    void fire();
    void setSelfDestroyTime(long timeMS);
    void setTimeoutTime(long timeMS);
    void setClientID(std::string clientid);
    std::string clientID();

    void appendResourceFilterRule(QString rule);
    void appendResourceFilterRule(QList<QString> rules);
    void setResourceFilterRule(QList<QString> rules);
    void removeResourceFilterRule(QString rules);
    QList<QString> resourceFilterRules();
    void setCookies(QVariantList cookies);
    QVariantList getCookies();

    private:
    QString m_url;
    QString m_name;
    QString m_id;
    int m_level;
    QString m_headers;
    QString m_useragent;
    long m_timeoutMs;
    long m_selfDestroyTimeMS;
    QList<QString> m_resourcesFilter;
    std::string m_clientID;
    QVariantList m_cookies;
};

class WebSpiderSyncRequest : public WebSpiderRequest {
    Q_OBJECT
    public:

    WebSpiderSyncRequest(QString url, QString spiderName);

    // For click and sendKeys function,
    // when wait timer timeout, we need
    // send parse to spider with this operator.
    void setRequestOpt(Operator *opt) { m_opt = opt; };

    // For click and sendKeys function,
    // return timeout error when customer wait for new page,
    // but no page is created before timeout.
    void stopWaitTimer();
    void startWaitTimer(long timeMS);

    private Q_SLOTS:
    void onTimeout();

    private:
    QTimer m_waitTimer;
    Operator *m_opt;
};

class WebSpiderDownloadRequest : public QObject {
    Q_OBJECT
    public:
    WebSpiderDownloadRequest(Operator *opt, QString clientid, QString spiderName, long ref, int timeout);

    long ref();
    void setSuccess();
    bool success();
    void setLink(QString link);
    QString link();
    QString clientID();
    void setHeaders(QVariantList headers);
    QVariantList headers();
    void setContentType(QString ctype);
    QString contentType();

    void end();

    private Q_SLOTS:
    void onTimeout();

    private:
    QTimer m_waitTimer;
    Operator *m_opt;
    QString m_spiderName;
    bool m_success;
    QString m_clientID;
    QString m_link;
    long m_downloadElementRef;
    QVariantList m_headers;
    QString m_contentType;
};

class WebSpiderRequestManager {
    public :
    ~WebSpiderRequestManager() {}

    static WebSpiderRequestManager *instance();

    WebSpiderRequest* startRequest (
            QString url, QString name, QVariantList cookies,
            int level = 100, long timeoutTime = 0, long destroyTimeMs = PAGE_DEFAULT_DESTROY_TIME_MS
    );

    WebSpiderRequest* createRequest (
            QString url, QString name,
            int level = 100, long timeoutTime = 0, long destroyTimeMs = PAGE_DEFAULT_DESTROY_TIME_MS
    );

    WebSpiderSyncRequest* createSyncRequest (
            QString url, QString name,
           int level = 100, long timeoutTime = 0, long destroyTimeMs = PAGE_DEFAULT_DESTROY_TIME_MS
    );

    bool isUrlInHistory(QString url);
    void cleanHistory();

    private:
    WebSpiderRequestManager() {}
    static WebSpiderRequestManager* m_instance;
    QList<QString> m_history;
};

class WebSpiderAround {
    public:
        WebSpiderAround(WebSpiderRequest *req)
            : m_request(req)
        {
        }
        ~WebSpiderAround()
        {
            if (m_request) 
                delete m_request;
        }

        void parse(Operator *opt);
        void remove(Operator *opt);

        QString requestUrl()
        {
            return m_request->url();
        }

        WebSpiderRequest *request()
        {
            return m_request;
        }

    private:
        WebSpiderRequest *m_request;

};

#endif

